自定义验证器

在 Angular 中,表单验证是确保用户输入数据有效性的重要手段。Angular 提供了内置的验证器,如 required、minLength 和 maxLength,但有时我们需要更复杂的验证逻辑。这时,自定义验证器就派上了用场。

1. 什么是自定义验证器?

自定义验证器是开发者编写的用于特定验证逻辑的函数。这些函数可以应用于 Angular 的模板驱动表单或响应式表单中,以确保用户输入符合特定的业务规则。

2. 自定义验证器的基本结构

自定义验证器本质上是一个函数,它接收一个 AbstractControl 类型的参数,并返回一个包含错误信息的对象或 null。如果验证失败,返回一个包含错误信息的对象;如果验证通过,则返回 null。

import { AbstractControl, ValidationErrors } from '@angular/forms';

export function customValidator(control: AbstractControl): ValidationErrors | null {
  // 验证逻辑
  if (/* 验证失败的条件 */) {
    return { customError: true };
  }
  return null;
}

3. 创建一个简单的自定义验证器

假设我们需要验证用户输入的电子邮件地址是否符合特定的格式(例如,必须包含 @example.com)。我们可以创建一个自定义验证器来实现这一逻辑。

3.1 编写自定义验证器函数

import { AbstractControl, ValidationErrors } from '@angular/forms';

export function emailDomainValidator(control: AbstractControl): ValidationErrors | null {
  const email = control.value;
  if (email && !email.endsWith('@example.com')) {
    return { invalidDomain: true };
  }
  return null;
}

3.2 在响应式表单中使用自定义验证器

在响应式表单中,我们可以将自定义验证器应用于表单控件。

import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { emailDomainValidator } from './email-domain.validator';

export class MyFormComponent {
  myForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      email: ['', [Validators.required, emailDomainValidator]]
    });
  }
}

3.3 在模板驱动表单中使用自定义验证器

在模板驱动表单中,我们需要将自定义验证器包装成一个指令。

import { Directive } from '@angular/core';
import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms';
import { emailDomainValidator } from './email-domain.validator';

@Directive({
  selector: '[emailDomain][ngModel]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: EmailDomainValidatorDirective, multi: true }
  ]
})
export class EmailDomainValidatorDirective implements Validator {
  validate(control: AbstractControl): ValidationErrors | null {
    return emailDomainValidator(control);
  }
}

然后在模板中使用该指令:

<input type="email" name="email" ngModel emailDomain>

4. 实践练习

4.1 任务描述

创建一个自定义验证器,用于验证用户输入的密码是否包含至少一个大写字母、一个小写字母和一个数字。

4.2 编写自定义验证器

import { AbstractControl, ValidationErrors } from '@angular/forms';

export function passwordValidator(control: AbstractControl): ValidationErrors | null {
  const password = control.value;
  const hasUpperCase = /[A-Z]/.test(password);
  const hasLowerCase = /[a-z]/.test(password);
  const hasNumber = /\d/.test(password);

  if (!hasUpperCase || !hasLowerCase || !hasNumber) {
    return { invalidPassword: true };
  }
  return null;
}

4.3 在表单中应用自定义验证器

在响应式表单中应用:

this.myForm = this.fb.group({
  password: ['', [Validators.required, passwordValidator]]
});

在模板驱动表单中应用:

@Directive({
  selector: '[passwordValidator][ngModel]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: PasswordValidatorDirective, multi: true }
  ]
})
export class PasswordValidatorDirective implements Validator {
  validate(control: AbstractControl): ValidationErrors | null {
    return passwordValidator(control);
  }
}
<input type="password" name="password" ngModel passwordValidator>

5. 总结

自定义验证器是 Angular 表单验证的重要组成部分,允许开发者根据业务需求实现复杂的验证逻辑。通过本教程,你应该已经掌握了如何创建和使用自定义验证器,并能够在实际项目中应用这些知识。

6. 进一步学习

  • 探索 Angular 的 FormArray 和 FormGroup 的验证。
  • 学习如何创建异步验证器。
  • 了解如何在自定义验证器中处理跨字段验证。

通过不断实践和学习,你将能够更灵活地使用 Angular 的表单验证功能,提升应用的用户体验和数据安全性。